package grammarLL1;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class TableLL1 {
	Map<Map<Symbol, Symbol>, List<Symbol>> table;
	
	public TableLL1() {
		table = new HashMap<Map<Symbol, Symbol>, List<Symbol>>();
	}

	public void put(Symbol nonTerminal, Symbol terminal, List<Symbol> ls) {
		Map<Symbol, Symbol> m = new HashMap<Symbol, Symbol>();
		
		m.put(nonTerminal, terminal);
		
		if (this.table.containsKey(m)) {
			m = null;
			return; // si pasara esto, la gramatica no seria LL1
		} else {
			if (Symbol.isNonTerminal(nonTerminal.toString()) && Symbol.isTerminal(terminal.toString())) {
				this.table.put(m, ls);
			} else if (Symbol.isNonTerminal(nonTerminal.toString()) && Symbol.isLambda(terminal)){
				List<Symbol> auxls = Grammar.getFirsts((NonTerminal)nonTerminal);
				
				// pone lambdas en todas las filas, para la columna del no-terminal nonTerminal,
				// siempre y cuando la fila no sea correspondiente a un terminal que es parte
				// de los Simbolos directrices de alguna produccion que comienza con nonTerminal
				for (Terminal t : Grammar.terminals.values()) {
					if (!auxls.contains(t)) {
						Map<Symbol, Symbol> auxm = new HashMap<Symbol, Symbol>();
						auxm.put(nonTerminal, t);
						List<Symbol> lambdaList = new LinkedList<Symbol>();
						lambdaList.add(terminal);
						this.table.put(m, lambdaList);
					}
				}
			} else {
				m = null;
				return; // no agrega nada porque no coinciden los simbolos
			}
		}
	}
	
	public List<Symbol> get(Symbol nonTerminal, Symbol terminal) {
		Map<Symbol, Symbol> m = new HashMap<Symbol, Symbol>();
		m.put(nonTerminal, terminal);
		return this.table.get(m);
	}
}
